/*
🦜 : They are here, but the old is there
*/

@Tag(name="应用", description="🦜: 应用列表，关键的和不好的")
@RestController
@RequestMapping("/app")
class AppController extends ControllerBase
{

    @EventListener
    public void init(ApplicationReadyEvent e) {
        System.out.println("⚙️ Initializing AppController");
        // put in some data
    }


} // AppController



// --------------------------------------------------
// within basic controller


// --------------------------------------------------

// @Disabled
class TestBasicCmdHistory extends TestBase{

    @Test
    void getCmdHistoryAll() throws JsonProcessingException{
        /*
          [
          {"id" : 0, "user": "user0", "cmd": "ls -l", "date": "2000-01-01 01:01:01", "illegal": "false"},
          {"id" : 1, "user": "user1", "cmd": "ls -l", "date": "2001-01-01 01:01:01", "illegal": "false"},
          {"id" : 2, "user": "user2", "cmd": "ls -l", "date": "2002-01-01 01:01:01", "illegal": "false"},
          {"id" : 3, "user": "user3", "cmd": "ls -l", "date": "2003-01-01 01:01:01", "illegal": "false"},
          {"id" : 4, "user": "user4", "cmd": "ls -l", "date": "2004-01-01 01:01:01", "illegal": "false"},
          {"id" : 5, "user": "user5", "cmd": "ls -l", "date": "2005-01-01 01:01:01", "illegal": "false"},
          {"id" : 6, "user": "user6", "cmd": "ls -l", "date": "2006-01-01 01:01:01", "illegal": "false"},
          {"id" : 7, "user": "user7", "cmd": "ls -l", "date": "2007-01-01 01:01:01", "illegal": "false"},
          {"id" : 8, "user": "user8", "cmd": "ls -l", "date": "2008-01-01 01:01:01", "illegal": "false"},
          {"id" : 9, "user": "user9", "cmd": "ls -l", "date": "2009-01-01 01:01:01", "illegal": "false"}
          ... 20 in total
          ]
        */
        JsonNode pageNode = getPage("/basic/getCmdHistory?pageNum=1&pageSize=2");
        pageNode = pageNode.get("data");
        assertEquals(20, pageNode.get("totalCount").asInt());
        ArrayNode voList = (ArrayNode)pageNode.get("voList");
        assertEquals(2, voList.size());
        assertEquals("user0", voList.get(0).get("user").asText());
    }

    @Test
    void getCmdHistoryBefore() throws JsonProcessingException{
        // get all that before 2005
        JsonNode pageNode = getPage("/basic/getCmdHistory?pageNum=1&pageSize=2&timeBefore=2005-01-01 01:01:01");
        pageNode = pageNode.get("data");
        assertEquals(5, pageNode.get("totalCount").asInt());
        ArrayNode voList = (ArrayNode)pageNode.get("voList");
        assertEquals(2, voList.size());
    }

    @Test
    void getCmdHistoryById() throws JsonProcessingException{
        // get all that before 2005
        JsonNode pageNode = getPage("/basic/getCmdHistory?pageNum=1&pageSize=2&id=5");
        pageNode = pageNode.get("data");
        assertEquals(1, pageNode.get("totalCount").asInt());
    }
}

// --------------------------------------------------
    @GetMapping("/getCmdHistory")
    @Operation(summary = "获取用户命令历史")
    public Dt.W<Dt.Page<Dt.CmdHistory>>
        getCmdHistory(
                      @RequestParam(defaultValue = "1")
                      @Parameter(description = "页码（从1开始）",
                                 examples = {@ExampleObject(name = "1", value = "1", description = "第一页"),}
                                 )
                      int pageNum,
                      @RequestParam(defaultValue = "2")
                      @Parameter(description = "每页多少条",
                                 examples = {@ExampleObject(name = "2", value = "2", description = "每页2条"),}
                                 )
                      int pageSize,
                      @RequestParam(required = false)
                      @Parameter(description = "ID",
                                 examples = {
                                        @ExampleObject(name = "1", value = "1", description = "查找ID=1的记录"),
                                 })
                      Long id,
                      @RequestParam(required = false)
                      @Parameter(description = "用户名",
                                 examples = {
                                     @ExampleObject(name = "aaa", value = "aaa", description = "查找用户aaa的记录"),
                                 })
                      String user,
                      @RequestParam(required = false)
                      @Parameter(description = "时间在这个时间之前（不包括）",
                                 examples = {
                                     @ExampleObject(name = "2020-01-01 01:01:01", value = "2020-01-01 01:01:01", description = "查找时间在2020-01-01 01:01:01之前的记录"),
                                 })
                      String timeBefore,
                      @RequestParam(required = false)
                      @Parameter(description = "按哪行排序", required = false, examples = {
                              @ExampleObject(name = "time", value = "time", description = "默认按时间排序"),
                          })
                      String sortBy,
                      @RequestParam(required = false)
                      @Parameter(description = "是否升序", required = false)
                      Boolean asc) throws JsonProcessingException {
        if (id != null) {
            Optional<Dt.CmdHistory> o = cmdHistoryRepo.findById(id);
            if (o.isPresent()) {
                return new Dt.W<Dt.Page<Dt.CmdHistory>>(0, new Dt.Page<Dt.CmdHistory>(new ArrayList<Dt.CmdHistory>(Arrays.asList(o.get())), 1L));
                // a page of 1
            }else{
                throw new RuntimeException("id not found");
            }
        }

        /*
          🦜 : 4 possibilities:

          | user | timeBefore | func                      |
          |------+------------+---------------------------|
          | v    |            | findByUser()              |
          |      | v          | findByTimeBefore()        |
          | v    | v          | findByUserAndTimeBefore() |
          |      |            | findAll()                 |
         */

        // 1. prepare the pageable
        // --------------------------------------------------
        final Set<String> sortBys = new HashSet<String>(Arrays.asList("time"));
        Pageable pageable = checkThingsAndPreparePageable(pageNum, pageSize, sortBys, sortBy, asc, "time");

        // 2. prepare the timeBefore
        // --------------------------------------------------
        Date timeBeforeDate = null;
        if (timeBefore != null) {
            DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime timeBeforeLocalDateTime = LocalDateTime.parse(timeBefore, fmt);
            timeBeforeDate = new2Old(timeBeforeLocalDateTime);
        }

        Page<Dt.CmdHistory> page;
        if (timeBeforeDate == null) {
            if (user == null || user.isEmpty()) { // --
                page = cmdHistoryRepo.findAll(pageable);
            } else {            // v-
                page = cmdHistoryRepo.findByUser(user, pageable);
            }
        }else{
            if (user == null || user.isEmpty()) { // -v
                page = cmdHistoryRepo.findByTimeBefore(timeBeforeDate, pageable);
            }else{
                page = cmdHistoryRepo.findByUserAndTimeBefore(user, timeBeforeDate, pageable);
            }
        }

        // vv
        return new Dt.W<Dt.Page<Dt.CmdHistory>>(0, new Dt.Page<Dt.CmdHistory>(page.getContent(),page.getTotalElements()));

    }

// --------------------------------------------------

        @Test
        void getAllUser() throws JsonProcessingException {
            /*
              🦜 : This should query the agent for all users. The mocked list should be
              Users: []*pb.UserInfo{
                {
                  Uid: "123", Name: "me",
                  HomeDir: "/home/me",
                  Description: "A normal user",
                  Shell: "/bin/bash",
                },
                {
                  Uid: "456", Name: "aaa",
                  HomeDir: "/home/aaa",
                  Description: "A normal user",
                  Shell: "/bin/bash",
                },
              },
             */
            JsonNode pageNode = getPage("/basic/getUsers");
            pageNode = pageNode.get("data");
            assertEquals(2, pageNode.get("totalCount").asInt());
            ArrayNode voList = (ArrayNode)pageNode.get("voList");
            assertEquals(2, voList.size());

            assertEquals("me", voList.get(0).get("name").asText());
            assertEquals("aaa", voList.get(1).get("name").asText());
        }

        @Test
        void getLoginHistoryAll() throws JsonProcessingException{
            /*
            🦜 : The mocked list:

			LoginInfos: []*pb.LoginInfo{
				{UserName: "me", Terminal: "tty2", LoginIp: "tty2", LoginTime: "2021-01-01 12:00:00", LogoutTime: "2021-01-01 22:00:00",},
				{UserName: "reboot", Terminal: "system boot", LoginIp: "6.2.0-39-generic", LoginTime: "2021-01-01 12:00:00", LogoutTime: "2021-01-01 22:00:00",},
				{UserName: "me", Terminal: "tty2", LoginIp: "tty2", LoginTime: "2022-01-01 12:00:00", LogoutTime: "2022-01-01 22:00:00",},
				{UserName: "me", Terminal: "tty2", LoginIp: "tty2", LoginTime: "2023-01-01 12:00:00", LogoutTime: "2023-01-01 22:00:00",},
			},
             */

            // 1. get the login history of all users, first page (2 per page), sorted by loginTime (descending, i.e. latest first)
            JsonNode pageNode = getPage("/basic/getLoginHistory?pageNum=1&pageSize=2&sortBy=loginTime&asc=false");
            pageNode = pageNode.get("data");
            assertEquals(4, pageNode.get("totalCount").asInt());
            ArrayNode voList = (ArrayNode)pageNode.get("voList");
            assertEquals(2, voList.size());

            assertEquals("me", voList.get(0).get("user").asText());
            assertEquals("me", voList.get(1).get("user").asText());
            assertEquals("2023-01-01 12:00:00", voList.get(0).get("loginTime").asText());
            assertEquals("2022-01-01 12:00:00", voList.get(1).get("loginTime").asText());
        }

        @Test
        void getLoginHistoryOneUser() throws JsonProcessingException{
            // 🦜 : Get the login history of user `me`, first page (2 per page), sorted by loginTime (descending, i.e. latest first)
            JsonNode pageNode = getPage("/basic/getLoginHistory?user=me&pageNum=1&pageSize=2&sortBy=loginTime&asc=false");
            pageNode = pageNode.get("data");
            assertEquals(3, pageNode.get("totalCount").asInt());
            ArrayNode voList = (ArrayNode)pageNode.get("voList");
            assertEquals(2, voList.size());

            assertEquals("me", voList.get(0).get("user").asText());
            assertEquals("me", voList.get(1).get("user").asText());
            assertEquals("2023-01-01 12:00:00", voList.get(0).get("loginTime").asText());
            assertEquals("2022-01-01 12:00:00", voList.get(1).get("loginTime").asText());

        }


// --------------------------------------------------

        repo.deleteAll();

        // 🦜 : Call the agent

        // 1. repare the request
        // --------------------------------------------------
        /*
          message GetLoginHistoryReq {
          string sinceTime = 1;
          string untilTime = 2;
          string user = 3;          // can be empty => get all users
          }
        */
        // sinceTime = Unix epoch
        // untilTime = today
        // DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime untilTime = LocalDateTime.now();
        // a year ago
        LocalDateTime sinceTime = untilTime.minusYears(1);
        GetLoginHistoryReq b = GetLoginHistoryReq.newBuilder()
            .setSinceTime(sinceTime.format(fmt))
            .setUntilTime(untilTime.format(fmt))
            .build();

        // 2. call the agent
        // --------------------------------------------------
        /*
          message LoginInfo {
          string user = 1;
          string terminal = 2;
          string loginIp = 3;           // where the user ssh from, or the tty if local login
          string loginTime = 4;
          string logoutTime = 5; // 登出时间 【特殊值释义 crash：系统崩溃或意外关机；down:用户图形界面登出】
          }

          message GetLoginHistoryRpl {
          repeated LoginInfo loginInfos = 1;
          }
        */
// ...

        // 3. pb -> java and save the result to db
        // --------------------------------------------------
        for (LoginInfo i : r.getLoginInfosList()) {
            repo.save(i2);
        }

/*
  --------------------------------------------------

  connection stats (got from netstat -lutp) within NetworkController

  🦜 : This is to ls which program is listening to which port. But it seems like only the 
 */

// --------------------------------------------------
